﻿using AutoMapper;
using Compass.PlanService.Domain;
using Compass.PlanService.Domain.Entities;
using Compass.PlanService.Infrastructure;
using Compass.Wasm.Shared;
using Compass.Wasm.Shared.Params;
using Compass.Wasm.Shared.Plans;

namespace Compass.Wasm.Server.Services.Plans;

public interface IPackingListService : IBaseService<PackingListDto>
{
    Task<ApiResponse<PackingListDto>> GetSingleByProjectIdAndBathAsync(PackingListParam param);
    Task<ApiResponse<PackingListDto>> GetPackingInfoAsync(PackingListParam param);
    Task<ApiResponse<PackingListDto>> AddByProjectIdAndBathAsync(PackingListDto dto);

    //MAUI
    Task<ApiResponse<PackingListDto>> GetSingleByMainPlanIdAsync(Guid mainPlanId);
    Task<ApiResponse<IEnumerable<PackingListDto>>> GetMauiPackingListDtosAsync(int skip, int take, string? search);
    Task<ApiResponse<PackingListDto>> GetSingleByOdpNumberAsync(string odpNumber);
}

public class PackingListService : IPackingListService
{
    #region ctor
    private readonly PlanDbContext _dbContext;
    private readonly IPlanRepository _repository;
    private readonly IMapper _mapper;
    public PackingListService(PlanDbContext dbContext, IPlanRepository repository, IMapper mapper)
    {
        _dbContext = dbContext;
        _repository = repository;
        _mapper = mapper;
    }
    #endregion

    #region 基本增删改查
    public async Task<ApiResponse<IEnumerable<PackingListDto>>> GetAllAsync()
    {
        try
        {
            var models = await _repository.GetPackingListsAsync();
            var orderModels = models.OrderByDescending(x => x.CreationTime);
            var dtos = await _mapper.ProjectTo<PackingListDto>(orderModels).ToListAsync();
            return new ApiResponse<IEnumerable<PackingListDto>> { Status = true, Result = dtos };
        }
        catch (Exception e)
        {
            return new ApiResponse<IEnumerable<PackingListDto>> { Status = false, Message = e.Message };
        }
    }

    public async Task<ApiResponse<PackingListDto>> GetSingleAsync(Guid id)
    {
        try
        {
            var model = await _repository.GetPackingListByIdAsync(id);
            if (model == null) return new ApiResponse<PackingListDto> { Status = false, Message = "查询数据失败" };
            var dto = _mapper.Map<PackingListDto>(model);
            return new ApiResponse<PackingListDto> { Status = true, Result = dto };
        }
        catch (Exception e)
        {
            return new ApiResponse<PackingListDto> { Status = false, Message = e.Message };
        }
    }

    public async Task<ApiResponse<PackingListDto>> AddAsync(PackingListDto dto)
    {
        try
        {
            var model = new PackingList(dto.Id.Value, dto.Product, dto.PackingType, dto.DeliveryType, dto.AssyPath);
            await _dbContext.PackingLists.AddAsync(model);
            dto.Id = model.Id;
            return new ApiResponse<PackingListDto> { Status = true, Result = dto };
        }
        catch (Exception e)
        {
            return new ApiResponse<PackingListDto> { Status = false, Message = e.Message };
        }
    }

    public async Task<ApiResponse<PackingListDto>> UpdateAsync(Guid id, PackingListDto dto)
    {
        try
        {
            var model = await _repository.GetPackingListByIdAsync(id);
            if (model == null) return new ApiResponse<PackingListDto> { Status = false, Message = "更新数据失败" };
            model.Update(dto);
            return new ApiResponse<PackingListDto> { Status = true, Result = dto };
        }
        catch (Exception e)
        {
            return new ApiResponse<PackingListDto> { Status = false, Message = e.Message };
        }
    }

    public async Task<ApiResponse<PackingListDto>> DeleteAsync(Guid id)
    {
        try
        {
            var model = await _repository.GetPackingListByIdAsync(id);
            if (model == null) return new ApiResponse<PackingListDto> { Status = false, Message = "删除数据失败" };
            model.SoftDelete();//软删除
            return new ApiResponse<PackingListDto> { Status = true };
        }
        catch (Exception e)
        {
            return new ApiResponse<PackingListDto> { Status = false, Message = e.Message };
        }
    }
    #endregion

    #region 扩展查询功能
    public async Task<ApiResponse<PackingListDto>> GetSingleByProjectIdAndBathAsync(PackingListParam param)
    {
        try
        {
            var mainPlan = await _repository.GetMainPlanByProjectIdAndBatchAsync(param.ProjectId.Value, param.Batch.Value);
            if (mainPlan == null) return new ApiResponse<PackingListDto> { Status = false };
            var model = await _repository.GetPackingListByIdAsync(mainPlan.Id);

            if (model == null) return new ApiResponse<PackingListDto> { Status = false, Message = "查询数据失败" };
            var dto = _mapper.Map<PackingListDto>(model);
            dto.ProjectId=mainPlan.ProjectId.Value;
            dto.Batch=mainPlan.Batch;
            dto.OdpNumber = mainPlan.Number;
            dto.ProjectName=mainPlan.Name;
            dto.FinishTime = mainPlan.FinishTime;

            return new ApiResponse<PackingListDto> { Status = true, Result = dto };
        }
        catch (Exception e)
        {
            return new ApiResponse<PackingListDto> { Status = false, Message = e.Message };
        }
    }

    public async Task<ApiResponse<PackingListDto>> GetPackingInfoAsync(PackingListParam param)
    {
        try
        {
            var mainPlan = await _repository.GetMainPlanByProjectIdAndBatchAsync(param.ProjectId.Value, param.Batch.Value);
            if (mainPlan == null) return new ApiResponse<PackingListDto> { Status = false };
            var model = await _repository.GetPackingListByIdAsync(mainPlan.Id);

            if (model == null) return new ApiResponse<PackingListDto> { Status = false, Message = "查询数据失败" };
            var dto = _mapper.Map<PackingListDto>(model);
            dto.ProjectId=mainPlan.ProjectId.Value;
            dto.Batch=mainPlan.Batch;
            dto.OdpNumber = mainPlan.Number;
            dto.ProjectName=mainPlan.Name;
            dto.FinishTime = mainPlan.FinishTime;

            return new ApiResponse<PackingListDto> { Status = true, Result = dto };
        }
        catch (Exception e)
        {
            return new ApiResponse<PackingListDto> { Status = false, Message = e.Message };
        }
    }

    public async Task<ApiResponse<PackingListDto>> AddByProjectIdAndBathAsync(PackingListDto dto)
    {
        var mainPlan = await _repository.GetMainPlanByProjectIdAndBatchAsync(dto.ProjectId.Value, dto.Batch.Value);
        dto.Id=mainPlan.Id;

        //2023.12.21，为了防止重复添加，应当先检查是否有重复的记录
        //有时候界面反应不过来，所以需要在后台防止这种事情发生
        var model = await _repository.GetPackingListByIdAsync(mainPlan.Id);
        //不存在时添加
        if (model == null) return await AddAsync(dto);
        //存在时更新
        return await UpdateAsync(model.Id, dto);
    }

    #endregion

    #region MAUI
    public async Task<ApiResponse<PackingListDto>> GetSingleByMainPlanIdAsync(Guid mainPlanId)
    {
        try
        {
            var model = await _repository.GetPackingListByIdAsync(mainPlanId);
            if (model == null) return new ApiResponse<PackingListDto> { Status = false, Message = "查询数据失败" };
            var dto = _mapper.Map<PackingListDto>(model);
            //todo:检查是否有托盘
            var plan =await _repository.GetMainPlanByIdAsync(mainPlanId);
            dto.OdpNumber = plan.Number;
            dto.ProjectName=plan.Name;
            dto.HavePallet = await _repository.HavePalletAsync(dto.Id.Value);

            return new ApiResponse<PackingListDto> { Status = true, Result = dto };
        }
        catch (Exception e)
        {
            return new ApiResponse<PackingListDto> { Status = false, Message = e.Message };
        }
    }

    public async Task<ApiResponse<IEnumerable<PackingListDto>>> GetMauiPackingListDtosAsync(int skip, int take, string? search)
    {
        try
        {
            //搜索，选出项目
            var models = await _repository.GetMainPlansAsync();
            var orderModels = models.OrderByDescending(x => x.FinishTime);
            var dtos = await orderModels.Where(x => string.IsNullOrEmpty(search) || 
                                                    x.Number.ToLower().Contains(search.ToLower()) || 
                                                    x.Name.ToLower().Contains(search.ToLower()))
                .Skip(skip)
                .Take(take)
                .Select(x => new PackingListDto()
                {
                    //轻量化信息
                    Id = x.Id,
                    OdpNumber = x.Number,
                    ProjectName = x.Name,
                    FinishTime = x.FinishTime,
                }).ToListAsync();
            //填充装箱信息
            foreach (var dto in dtos)
            {
                await GetPackingListInfo(dto);
            }
            
            return new ApiResponse<IEnumerable<PackingListDto>> { Status = true, Result =dtos };
        }
        catch (Exception e)
        {
            return new ApiResponse<IEnumerable<PackingListDto>> { Status = false, Message = e.Message };
        }
    }

    private async Task GetPackingListInfo(PackingListDto dto)
    {
        //此逻辑不对，应该是看有没有packinglist
        var pkList = await _repository.GetPackingListByIdAsync(dto.Id.Value);
        dto.HavePackingList = pkList!=null;
        if (dto.HavePackingList)
        {
            dto.Product = pkList.Product;
            dto.PackingType = pkList.PackingType;
            dto.DeliveryType = pkList.DeliveryType;

            dto.HavePallet = await _repository.HavePalletAsync(dto.Id.Value);
        }
    }

    public async Task<ApiResponse<PackingListDto>> GetSingleByOdpNumberAsync(string odpNumber)
    {
        try
        {
            var model = await _repository.GetPackingListByOdpNumberAsync(odpNumber);
            if (model == null) return new ApiResponse<PackingListDto> { Status = false, Message = "查询数据失败" };
            var dto = _mapper.Map<PackingListDto>(model);
            //todo:检查是否有托盘
            var plan = await _repository.GetMainPlanByIdAsync(dto.Id.Value);
            dto.OdpNumber = plan.Number;
            dto.ProjectName=plan.Name;
            dto.HavePallet = await _repository.HavePalletAsync(dto.Id.Value);

            return new ApiResponse<PackingListDto> { Status = true, Result = dto };
        }
        catch (Exception e)
        {
            return new ApiResponse<PackingListDto> { Status = false, Message = e.Message };
        }
    }

    #endregion
}